/**
 * MCU GPIO 驱动适配层头文件
 * Copyright (c) 2021 深圳市智辰科技有限公司
 * All rights reserved.
 */

#ifndef _GPIO_H_
#define _GPIO_H_

#include <hal/gpio_types.h>

#include "stdc.h"
#include "std_type.h"
#include "std_err.h"

#ifdef __cplusplus
extern "C" {
#endif


#define ESP_INTR_FLAG_DEFAULT 0

#ifdef ESP8266
    /**
     * 与 ESP32-IDF 保持一致
     */
    #define GPIO_PIN_INTR_DISABLE    GPIO_INTR_DISABLE
    #define GPIO_PIN_INTR_POSEDGE    GPIO_INTR_POSEDGE
    #define GPIO_PIN_INTR_NEGEDGE    GPIO_INTR_NEGEDGE
    #define GPIO_PIN_INTR_ANYEDGE    GPIO_INTR_ANYEDGE
    #define GPIO_PIN_INTR_LOW_LEVEL  GPIO_INTR_LOW_LEVEL
    #define GPIO_PIN_INTR_HIGH_LEVEL GPIO_INTR_HIGH_LEVEL
    #define GPIO_PIN_INTR_MAX        GPIO_INTR_MAX
#endif // ESP8266

typedef enum {
	GPIO_MODEX_NULL = 0,  // 禁用
	GPIO_MODEX_IPU,       // 上拉输入
	GPIO_MODEX_IPD,       // 下拉输入
	GPIO_MODEX_OPPL,      // 推挽输出，初始输出低电平
	GPIO_MODEX_OPPH,      // 推挽输出，初始输出高电平
	GPIO_MODEX_OODL,      // 开漏输出，初始输出低电平
	GPIO_MODEX_OODH,      // 开漏输出，初始输出高电平
	GPIO_MODEX_MAX
} gpio_modex_t;

/**
 * 参数版 gpio_config()
 */
std_err_t GPIO_Config(gpio_num_t pin, gpio_mode_t mode, gpio_pullup_t pull_up_en, gpio_pulldown_t pull_down_en, gpio_int_type_t intr_type);
std_err_t GPIO_ConfigX(gpio_num_t pin, gpio_modex_t mode, gpio_int_type_t intr);

/**
 * GPIO APIs 函数类型声明
 */
typedef std_err_t (*FUNC_GPIO_ConfigX)(gpio_modex_t mode, gpio_int_type_t intr_type);
typedef std_err_t (*FUNC_GPIO_Config)(gpio_mode_t mode, gpio_pullup_t pull_up_en, gpio_pulldown_t pull_down_en, gpio_int_type_t intr_type);
typedef std_err_t (*FUNC_GPIO_Toggle)();
typedef int       (*FUNC_GPIO_In)();
typedef std_err_t (*FUNC_GPIO_Out)(uint8_t x);
typedef std_err_t (*FUNC_GPIO_IntEnable)(gpio_int_type_t trig);
typedef std_err_t (*FUNC_GPIO_IntDisable)();
typedef std_err_t (*FUNC_GPIO_Switch)(uint8_t x);

/**
 * 声明命名的 GPIO APIs(基本的)
 */
#define GPIO_DECLARE(NAME) \
	extern const gpio_num_t GPIO_##NAME; \
	std_err_t GPIO_##NAME##_ConfigX(gpio_modex_t mode, gpio_int_type_t intr_type); \
	std_err_t GPIO_##NAME##_Config(gpio_mode_t mode, gpio_pullup_t pull_up_en, gpio_pulldown_t pull_down_en, gpio_int_type_t intr_type); \
	void      GPIO_##NAME##_Toggle(); \
	uint8_t        GPIO_##NAME##_In(); \
	void      GPIO_##NAME##_Out(uint8_t x); \
	std_err_t GPIO_##NAME##_IntEnable(gpio_int_type_t trig); \
	std_err_t GPIO_##NAME##_IntDisable(); \
	std_err_t GPIO_##NAME##_IntRegisterIsr(gpio_isr_t isr_handler, void* args); \
	std_err_t GPIO_##NAME##_IntRemoveIsr();

/**
 * 声明命名的 GPIO APIs(带极性的)
 */
#define GPIO_DECLARE_POLARITY(NAME) \
	GPIO_DECLARE(NAME) \
	extern const int GPIO_##NAME##_TRIG_LEVEL; \
	void      GPIO_##NAME##_On(); \
	void      GPIO_##NAME##_Off(); \
	void      GPIO_##NAME##_Switch(uint8_t on); \
	uint8_t   GPIO_##NAME##_IsInOn(); \
	uint8_t   GPIO_##NAME##_IsInOff(); \
	uint8_t   GPIO_##NAME##_Polarity();


/**
 * 定义命名的 GPIO APIs(基本的)
 */
#define GPIO_DEFINE(NAME, PIN) \
	const gpio_num_t GPIO_##NAME                            = PIN; \
	std_err_t GPIO_##NAME##_ConfigX(gpio_modex_t mode, gpio_int_type_t intr_type) { return GPIO_ConfigX(PIN, mode, intr_type); } \
	std_err_t GPIO_##NAME##_Config(gpio_mode_t mode, gpio_pullup_t pull_up_en, gpio_pulldown_t pull_down_en, gpio_int_type_t intr_type) \
															{ return GPIO_Config(PIN, mode, pull_up_en, pull_down_en, intr_type); } \
	void      GPIO_##NAME##_Toggle()                        { gpio_set_level(PIN, !gpio_get_level(PIN)); } \
	uint8_t        GPIO_##NAME##_In()                            { return gpio_get_level(PIN); } \
	void      GPIO_##NAME##_Out(uint8_t x)                       { gpio_set_level(PIN, x); } \
	std_err_t GPIO_##NAME##_IntEnable(gpio_int_type_t trig) { return gpio_set_intr_type(PIN, trig); } \
	std_err_t GPIO_##NAME##_IntDisable()                    { return gpio_set_intr_type(PIN, GPIO_INTR_DISABLE); } \
	std_err_t GPIO_##NAME##_IntRegisterIsr(gpio_isr_t isr_handler, void* args) \
															{ return gpio_isr_handler_add(PIN, isr_handler, args); } \
	std_err_t GPIO_##NAME##_IntRemoveIsr()      	        { return gpio_isr_handler_remove(PIN); }

/**
 * 定义命名的 GPIO APIs(带极性的)
 */
#define GPIO_DEFINE_POLARITY(NAME, PIN, LEVEL) \
	GPIO_DEFINE(NAME, PIN) \
	const int GPIO_##NAME##_TRIG_LEVEL						= LEVEL; \
	void      GPIO_##NAME##_On()          			        { GPIO_##NAME##_Out(LEVEL); } \
	void      GPIO_##NAME##_Off()         				    { GPIO_##NAME##_Out(!LEVEL); } \
	void      GPIO_##NAME##_Switch(uint8_t on) 				    { (!on == !LEVEL)?GPIO_##NAME##_Out(1):GPIO_##NAME##_Out(0); } \
	uint8_t        GPIO_##NAME##_IsInOn()      				    { return (GPIO_##NAME##_In() == LEVEL); } \
	uint8_t        GPIO_##NAME##_IsInOff()     				    { return (GPIO_##NAME##_In() != LEVEL); } \
	uint8_t        GPIO_##NAME##_Polarity()      			    { return LEVEL; }

/**
 * 外部中断触发类型
 typedef enum {
    GPIO_INTR_DISABLE = 0,     // Disable GPIO interrupt
    GPIO_INTR_POSEDGE = 1,     // GPIO interrupt type : rising edge
    GPIO_INTR_NEGEDGE = 2,     // GPIO interrupt type : falling edge
    GPIO_INTR_ANYEDGE = 3,     // GPIO interrupt type : both rising and falling edge
    GPIO_INTR_LOW_LEVEL = 4,   // GPIO interrupt type : input low level trigger
    GPIO_INTR_HIGH_LEVEL = 5,  // GPIO interrupt type : input high level trigger
    GPIO_INTR_MAX,
} gpio_int_type_t;
*/
typedef enum {
	EXTI_Trigger_Disable = GPIO_INTR_DISABLE,
	EXTI_Trigger_Rising = GPIO_INTR_POSEDGE,
	EXTI_Trigger_Falling = GPIO_INTR_NEGEDGE,
	EXTI_Trigger_Rising_Falling = GPIO_INTR_ANYEDGE,
} EXTI_Trigger_TypeDef;


#ifdef __cplusplus
}
#endif

#endif // _GPIO_H_
